package String;

import Static.Person;
import org.junit.Test;

/**
 * String 对象会将字符串保存在char[]中，
 *
 *String 当字面量赋值时    String s1 = "abc";
 * 当对字符串重新赋值，不会改变原来的值，会重新创建一个新的值在方法区的字符串常量池中
 * 当对字符串进行连结拼接操作，不会改变原来的值，会重新创建一个新的值
 *
 * String 实例化对象时    String s1 = new String("abc");
 *在堆空间开辟空间，变量s1在栈中保存堆空间的地址，堆空间里保存常量池中的"abc"的地址
 *
 * 面试题  String s1 = new String("abc")； 在内存中创建了几个对象？
 *  2 个  一个是在对空间创建的String对象，另一个是char[]在常量池创建的"abc"
 */
public class Demo1 {
    public static void main(String[] args) {
        String s1 = "abc";//字面量赋值和创建字符串对象效果一样
//       =String s1 = new String("abc");
        String s2 = "abc";
        //通过字面量给字符串赋值，内容存在常量池中，
        // 栈中的变量名存的是字符串在常量池的地址
        //常量池不会创建相同的字符串，所以都指向通过一个"abc"
        System.out.println(s1==s2);//true

        s1 = "hello";
        System.out.println(s1);//hello
        //重新给s1赋值，就会在常量池中创建一个新的字符串
        //把新的地址给变量s1

        String s3 = "abc";
        s3 = s3 +"def";
        System.out.println(s3);//abcdef
        //拼接字符串，也是创建新的值

        String s4 = "abc";
        String s5 = s4.replace('a', 'm');
        //修改字符串中指定的字符时，也必须重新创建一个新的值
        System.out.println(s4);//abc
        System.out.println(s5);//mbc

        //String s1 = "abc";
        String s6 = new String("abc");
        String s7 = new String("abc");
        //s1存的是常量池的地址，s6存的是堆中的地址，
        // 堆中的空间存的是常量池里"abc"的地址
        System.out.println(s1 == s6);//false
        //s6 和s7创建了两个不一样的对象，所以堆中的地址肯定不一样
        System.out.println(s6 == s7);//false

        Person p1 = new Person("tom",10);
        Person p2 = new Person("tom",10);
        System.out.println(p1 == p2);//false
//        System.out.println(p1.name.equals(p2.name));true
//        System.out.println(p1.name == p2.name);true
        //对象中的name本质是存的常量池的"tom"的地址

        String s11 = "java";
        String s12 = "EE";
        String s13 = "javaEE";
        String s14 = "java"+"EE";
        String s15 = s11+"EE";
        String s16 = "java"+s12;
        String s17 = s11+s12;
        String s18 = s17.intern();//这个方法的返回值s18使用的是常量池中的"javaEE"的地址


        System.out.println(s13 == s14);//true
        System.out.println(s13 == s15);//false
        System.out.println(s13 == s16);//false
        System.out.println(s13 == s17);//false
        System.out.println(s15 == s16);//false
        System.out.println(s15 == s17);//false
        System.out.println(s16 == s17);//false
        System.out.println(s13 == s18);//true

//        结论：常量与常量的拼接结果仍在常量池，常量池不会存在相同内容的常量。
        //      只要其中有一个是变量名，就会在堆中创建一个对象，栈中的变量存的就是堆中的地址
        //      堆中的内容是常量池字符串的地址
    }


}
